home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 9 code / Faceless Background Apps / main.c next >
Encoding:
C/C++ Source or Header  |  1995-06-16  |  10.4 KB  |  359 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    Apple Developer Technical Support
  4. #
  5. #    SmallDaemon
  6. #    A small faceless background-only application
  7. #
  8. #    main.c    -    C Source
  9. #
  10. #    Copyright © 1991-1995 Apple Computer, Inc.
  11. #    All rights reserved.
  12. #
  13. #    Versions:   
  14. #        1.0.2    06/95    Jim Luther        Added IncreaseApplicationStack from the
  15. #                                        Tech Note "PS 2 - Background-Only Applications".
  16. #        1.0.1    02/95    Jim Luther        Cleaned up source and made it compatible
  17. #                                        with the Universal Interfaces.
  18. #        1.0        09/91    C.K. Haun <TR>
  19. #   
  20. #    Components:
  21. #        main.c
  22. #        AppleEvents.c
  23. #
  24. #    This is a _very_ simple sample showing a do-nothing 
  25. #    System 7.0 faceless background application.  
  26. #    The main things to note are…
  27. #    1)    Look at the SIZE resource for the flag settings you'll
  28. #        need to let the Finder™ know that you only want to work
  29. #        in the background.
  30. #    2)    Notice that you really do have your own heap and your own
  31. #        event loop.  You can do anything a foreground application
  32. #        can do, send AppleEvents, PPC stuff, anything else you'd
  33. #        like EXCEPT a graphic interface.
  34. #    3)    NOTE that no managers are started up.  You cannot start up
  35. #        Window, Menu, Dialogs, or anything else that 
  36. #        deals with the graphic front end.  Just leave them out.
  37. #        You _should_ start up QuickDraw, to use some 
  38. #        QuickDraw functions (like offscreen ports) and because
  39. #        other parts of the Macintosh Toolbox (parts which you may 
  40. #        not suspect) depend on having QuickDraw initialized,
  41. #        but you CANNOT actually do any screen drawing.
  42. #
  43. #    Of course, a backgrounder can be launched from the Finder™ 
  44. #    with a double-click.  However, if you'd like the backgrounder
  45. #    to perform some useful service for your main application, driver,
  46. #    DA, or whatever, you will want it running all the time.
  47. #    The BEST way to insure this is to install the backgrounder in the
  48. #    StartUp Items folder in the system folder.  This will insure that
  49. #    it is always launched, and it will also reduce memory fragmentation
  50. #    since it will be installed at startup time.  You can search for it
  51. #    when you need it with IPCListPorts (see the PPC toolbox documentation).
  52. #    Optionally, you can use the LaunchApplication trap to launch it 
  53. #    when you need it, and kill it when you're done.  But this could 
  54. #    cause some multiFinder heap fragmentation.
  55. #
  56. #    And remember, it's a backgrounder, you can't see it.  To kill it
  57. #    use TaskIt or ProcDoggie.
  58. #
  59. # ---------------------------------------------------------------
  60. #    Use this sample as a starting point, and adapt its' routines to 
  61. #    meet the specific needs of your project.  
  62. #
  63. ------------------------------------------------------------------------------*/
  64.  
  65. /*
  66. **    This doesn't do much but wait for a quit event.  But, you can expand it
  67. **    to suit whatever your needs are for a backgrounder.
  68. **    Be sure to look at the SIZE resource for this app to see how the
  69. **    flags should be set for a background-only task.
  70. */
  71.  
  72. #include <Types.h>
  73. #include <MixedMode.h>
  74. #include <Memory.h>
  75. #include <Errors.h>
  76. #include <OSUtils.h>
  77. #include <QuickdrawText.h>
  78. #include <QuickDraw.h>
  79. #include <Events.h>
  80. #include <AppleTalk.h>
  81. #include <Files.h>
  82. #include <PPCToolbox.h>
  83. #include <Processes.h>
  84. #include <EPPC.h>
  85. #include <Notification.h>
  86. #include <AppleEvents.h>
  87. #include <Gestalt.h>
  88. #include <SegLoad.h>
  89.  
  90. /*
  91. **    Constants
  92. */
  93.  
  94. enum
  95. {
  96.     /*
  97.     **    A long time, long time. Change this if you'd like to do
  98.     **    null processing or if you're depending on WakeUpProcess called from
  99.     **    a completion routine to start non-interrupt processingh. Just keep
  100.     **    in mind that the user does NOT know that you exist, and if you are
  101.     **    eating up a bunch of time, the user will not know why the system
  102.     **    is slowing down.
  103.     */
  104.     kSleepTime = 50000
  105. };
  106.  
  107. /*
  108. **    Types
  109. */
  110.  
  111. /* A little struct to install AE handlers from.  Makes it easier to plug in */
  112. /* new handlers. */
  113. struct AEinstalls
  114. {
  115.     AEEventClass        theClass;
  116.     AEEventID            theEvent;
  117.     ProcPtr                theProc;
  118. };
  119. typedef struct AEinstalls AEinstalls;
  120.  
  121. /*
  122. **    Global variables
  123. */
  124.  
  125. Boolean            gQuit = false;
  126. EventRecord        gERecord;
  127. Boolean            gHasAppleEvents;
  128. unsigned long    gMySleep = kSleepTime;  
  129.  
  130.  
  131. /*
  132. **    Function prototypes
  133. */
  134.  
  135. OSErr IncreaseApplicationStack(Size incrementSize);
  136. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  137. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  138. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  139. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  140. void DoHighLevel(EventRecord *AERecord);
  141. void InitAEStuff(void);
  142.  
  143. void main(void)
  144. {
  145.     /*
  146.     **    If your FBA needs extra stack space, call IncreaseApplicationStack here
  147.     **    to increase the stack space. Remember to increase your heap size by the
  148.     **    the same amount.
  149.     */
  150. //    IncreaseApplicationStack(22*1024);    /* Get another 22K of stack space */
  151.     
  152.     /*
  153.     **    We are NOT initializing any managers except for QuickDraw.  We're in
  154.     **    the background, with no user interface, we can't use windows or dialogs
  155.     **    or menus.  If you need to talk to the user you can post a notification,
  156.     **    or launch an application to communicate. Passing an AppleEvent in the
  157.     **    launchapplication trap could do the communication for you.
  158.     */
  159.     
  160.     InitGraf(&qd.thePort);
  161.     
  162.     /* Routine to install Apple event handlers */
  163.     InitAEStuff();
  164.     
  165.     /* no nothing but high level events */
  166.     while ( gQuit == false )
  167.     {
  168.         (void) WaitNextEvent(highLevelEventMask, &gERecord, gMySleep, 0);
  169.         switch ( gERecord.what )
  170.         {
  171.             case nullEvent:
  172.                 /* no null processing in this example */
  173.                 break;
  174.             
  175.             case kHighLevelEvent:
  176.                 DoHighLevel(&gERecord);
  177.                 break;
  178.             
  179.             default:
  180.                 break;
  181.         }
  182.     }
  183. }
  184.  
  185. /*
  186. **    Increase the space allocated for the application stack.
  187. **
  188. **    Warning: SetApplLimit always sets the stack to at least as large as the 
  189. **        default stack for the machine (8K on machines with original QuickDraw,  
  190. **        24K on machines with Color QuickDraw), so the application partition 
  191. **        must be large enough to accommodate an appropriate stack and heap.
  192. **    
  193. **        Call this only once, at the beginning of the application.
  194. **
  195. **    Another warning:
  196. **        Don't bother trying to set the stack size to something lower than 24K.
  197. **        If SetApplLimit is called to do this, it will silently lower ApplLimit
  198. **        to a 24K stack.
  199. */
  200. OSErr IncreaseApplicationStack(Size incrementSize)
  201. {
  202.     OSErr result;
  203.  
  204.     /* Increase the stack size by lowering the heap limit. */
  205.     SetApplLimit((Ptr) ((unsigned long) GetApplLimit() - incrementSize));
  206.     result = MemError();
  207.     if ( result == noErr )
  208.         MaxApplZone();
  209.         
  210.     return ( result );
  211. }
  212.  
  213. /*
  214. **    Here are the AppleEvent handlers for this background-only task.
  215. **    Since this is a real live application, it can accept and send any
  216. **    Apple Events you want to send or receive.
  217. **    In this case, the only ones that make any sense in this app are
  218. **    'oapp' and 'quit'
  219. */
  220.  
  221. /*
  222. **    InitAEStuff checks for the availability of the AppleEvent Manager and
  223. **    installs our event handlers.
  224. **    If the AppleEvent Manager isn't around, we bail.
  225. */
  226. void InitAEStuff(void)
  227. {
  228.     static    AEinstalls HandlersToInstall[] =
  229.     {
  230.         {
  231.             kCoreEventClass, kAEOpenApplication, (ProcPtr)AEOpenHandler
  232.         },
  233.         {
  234.             kCoreEventClass, kAEOpenDocuments, (ProcPtr)AEOpenDocHandler
  235.         },
  236.         {
  237.             kCoreEventClass, kAEQuitApplication, (ProcPtr)AEQuitHandler
  238.         },
  239.         {
  240.             kCoreEventClass, kAEPrintDocuments, (ProcPtr)AEPrintHandler
  241.         }, 
  242.         /* The above are the four required AppleEvents. */
  243.     };
  244.     
  245.     OSErr    aevtErr = noErr;
  246.     long    aLong = 0;
  247.     Boolean    gHasAppleEvents = false;
  248.     
  249.     /*
  250.     **    Check this machine for AppleEvents. If they are not here (ie not 7.0)
  251.     **    then we exit
  252.     */
  253.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  254.     
  255.     /*
  256.     **    The following series of calls installs all our AppleEvent Handlers.
  257.     **    These handlers are added to the application event handler list that 
  258.     **    the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  259.     **    and we call AEProcessEvent, the AppleEvent manager will check our
  260.     **    list of handlers and dispatch to it if there is one.
  261.     */
  262.     if ( gHasAppleEvents )
  263.     {
  264.         register qq;
  265.         for ( qq = 0;
  266.               qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls)));
  267.               qq++)
  268.         {
  269.             aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
  270.                                             NewAEEventHandlerProc(HandlersToInstall[qq].theProc), 0, false);
  271.             if ( aevtErr != noErr )
  272.             {
  273.                 /*
  274.                 **    Of course, you can't tell the user why you died directly,
  275.                 **    since you have no face. But, you can post a notification
  276.                 **    from here to let them know.
  277.                 */
  278.                 ExitToShell();    /* just fail, baby */
  279.             }
  280.         }
  281.     }
  282.     else
  283.     {
  284.         ExitToShell();
  285.     }
  286. }
  287.  
  288.  
  289. void DoHighLevel(EventRecord *AERecord)
  290. {
  291.     /*
  292.     **    I'm not doing any error handling here because there's not a lot
  293.     **    I can do, just pass the errors back.
  294.     */
  295.     AEProcessAppleEvent(AERecord);
  296. }
  297.  
  298.  
  299. /* This is the standard Open Application event. */
  300. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  301. {
  302. #pragma unused (messagein,reply,refIn)
  303.     /*
  304.     **    We of course don't do anything here, since we're background only
  305.     **    But this was a normal launch, so return noErr
  306.     */
  307.     return ( noErr );
  308. }
  309.  
  310.  
  311. /*
  312. **    Open Doc, opens our documents.
  313. **    In this case, of course, you are in the background so you should return
  314. **    an error here since you're not opening a document.
  315. **    Of course, you _might_ want to open a doc, but you will probably
  316. **    confuse the user if you do, since they will see no action as the
  317. **    result of their clicking on a document icon.
  318. */
  319. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  320. {
  321. #pragma unused (reply, refIn,messagein)
  322.     /*
  323.     **    We of course don't do anything here, so tell the sender that we
  324.     **    didn't handle the event
  325.     */
  326.     return ( errAEEventNotHandled );
  327. }
  328.  
  329.  
  330. /* Same logic for printing */
  331. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  332. {
  333. #pragma unused (reply,refIn,messagein)
  334.     /*
  335.     **    We of course don't do anything here, so tell the sender that we
  336.     **    didn't handle the event
  337.     */
  338.     return ( errAEEventNotHandled );
  339. }
  340.  
  341.  
  342. /*
  343. **    Standard Quit event handler, to handle a Quit event from the Finder,
  344. **    for example.
  345. **    ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have
  346. **    a happy life.
  347. */
  348. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  349. {
  350. #pragma unused (messagein,refIn,reply)
  351.     /*
  352.     **    This does _NOT_ quit, you should NEVER quit from an AppleEvent
  353.     **    handler.  Calling ExitToShell here would blow up the Finder™
  354.     */
  355.     gQuit = true;
  356.     return ( noErr );
  357. }
  358.